/********************************************************************************************************
 * @file    ota.h
 *
 * @brief   This is the header file for BLE SDK
 *
 * @author  BLE GROUP
 * @date    06,2022
 *
 * @par     Copyright (c) 2022, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
 *
 *          Licensed under the Apache License, Version 2.0 (the "License");
 *          you may not use this file except in compliance with the License.
 *          You may obtain a copy of the License at
 *
 *              http://www.apache.org/licenses/LICENSE-2.0
 *
 *          Unless required by applicable law or agreed to in writing, software
 *          distributed under the License is distributed on an "AS IS" BASIS,
 *          WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *          See the License for the specific language governing permissions and
 *          limitations under the License.
 *
 *******************************************************************************************************/
#ifndef OTA_H_
#define OTA_H_


/**
 * @brief 	Legacy OTA command
 */
#define CMD_OTA_VERSION						0xFF00	//client -> server
#define CMD_OTA_START						0xFF01	//client -> server
#define CMD_OTA_END							0xFF02	//client -> server

/**
 * @brief 	Extended OTA command
 */
#define CMD_OTA_START_EXT					0xFF03	//client -> server
#define CMD_OTA_FW_VERSION_REQ				0xFF04	//client -> server
#define CMD_OTA_FW_VERSION_RSP				0xFF05	//server -> client
#define CMD_OTA_RESULT						0xFF06	//server -> client
#define CMD_OTA_SCHEDULE_PDU_NUM			0xFF08	//server -> client
#define CMD_OTA_SCHEDULE_FW_SIZE			0xFF09	//server -> client



/**
 * @brief	OTA result
 */
enum{
	//0x00
	OTA_SUCCESS 			= 0,			//success
	OTA_DATA_PACKET_SEQ_ERR,				//OTA data packet sequence number error: repeated OTA PDU or lost some OTA PDU
	OTA_PACKET_INVALID,						//invalid OTA packet: 1. invalid OTA command; 2. addr_index out of range; 3.not standard OTA PDU length
	OTA_DATA_CRC_ERR,						//packet PDU CRC err

	//0x04
	OTA_WRITE_FLASH_ERR,					//write OTA data to flash ERR
 	OTA_DATA_INCOMPLETE,					//lost last one or more OTA PDU
 	OTA_FLOW_ERR,		    				//peer device send OTA command or OTA data not in correct flow
 	OTA_FW_CHECK_ERR,						//firmware CRC check error

	//0x08
	OTA_VERSION_COMPARE_ERR,				//the version number to be update is lower than the current version
	OTA_PDU_LEN_ERR,						//PDU length error: not 16*n, or not equal to the value it declare in "CMD_OTA_START_EXT" packet
	OTA_FIRMWARE_MARK_ERR,		    		//firmware mark error: not generated by telink's BLE SDK
	OTA_FW_SIZE_ERR,						//firmware size error: no firmware_size; firmware size too small or too big

	//0x0C
	OTA_DATA_PACKET_TIMEOUT,	   			//time interval between two consequent data packet exceed, time out value can be set by API "blc_ota_setOtaDataPacketTimeout"
 	OTA_TIMEOUT,							//OTA flow total timeout, time out value can be set by API "blc_ota_setOtaProcessTimeout"
 	OTA_FAIL_DUE_TO_CONNECTION_TERMINATE,	//OTA fail due to current connection terminate(maybe connection timeout or local/peer device terminate connection)
	OTA_MCU_NOT_SUPPORTED,					//MCU does not support this OTA mode

	//0x10
	OTA_LOGIC_ERR,							//software logic error, please contact FAE of TeLink
};




/**
 *  @brief data structure of OTA command "CMD_OTA_START"
 */
typedef struct {
	u16  	ota_cmd;
} ota_start_t;


/**
 *  @brief data structure of OTA command "CMD_OTA_END"
 */
typedef struct {
	u16  	ota_cmd;
	u16		adr_index_max;
	u16		adr_index_max_xor;
} ota_end_t;


/**
 *  @brief data structure of OTA command "CMD_OTA_START_EXT"
 */
typedef struct {
	u16  	ota_cmd;
	u8		pdu_length;			//must be: 16*n(n is in range of 1 ~ 15); pdu_length: 16,32,48,...240
	u8		version_compare;	//0: no version compare; 1: only higher version can replace lower version
	u8		rsvd[16];			//reserved for future use
} ota_startExt_t;


/**
 *  @brief data structure of OTA command "CMD_OTA_RESULT"
 */
typedef struct {
	u16  	ota_cmd;
	u8		result;
	u8		rsvd;
} ota_result_t;



/**
 *  @brief data structure of OTA command "CMD_OTA_FW_VERSION_REQ"
 */
typedef struct {
	u16  	ota_cmd;
	u16		version_num;
	u8		version_compare;   //1: only higher version can replace lower version
} ota_versionReq_t;


/**
 *  @brief data structure of OTA command "CMD_OTA_FW_VERSION_RSP"
 */
typedef struct {
	u16  	ota_cmd;
	u16		version_num;
	u8		version_accept;      //1: accept firmware update; 0: reject firmware update(version compare enable, and compare result: fail)
} ota_versionRsp_t;


/**
 *  @brief data structure of OTA command "CMD_OTA_SCHEDULE_PDU_NUM"
 */
typedef struct {
	u16  	ota_cmd;
	u16  	success_pdu_cnt;	// successful OTA PDU number
} ota_sche_pdu_num_t;

/**
 *  @brief data structure of OTA command "CMD_OTA_SCHEDULE_FW_SIZE"
 */
typedef struct {
	u16  	ota_cmd;
	u32		success_fw_size;	// successful OTA firmware size (unit: Byte)
} ota_sche_fw_size_t;



/**
 * @brief      ota crc32 related function.
 * @param[in]  crc: initial crc value.
 * @param[in]  input: input data.
 * @param[in]  table: crc calculate table.
 * @param[in]  len: data length.
 * @return     crc result.
 */
unsigned long crc32_half_cal(unsigned long crc, unsigned char* input, unsigned long* table, int len);

/**
 * @brief      ota crc32 related function.
 * @param[in]  crc: initial crc value.
 * @param[in]  input: input data.
 * @param[in]  table: crc calculate table.
 * @param[in]  len: data length.
 * @return     crc result.
 */
unsigned long crc32_cal(unsigned long crc, unsigned char* input, unsigned long* table, int len);

/**
 * @brief      ota crc16 related function.
 * @param[in]  pD: input data.
 * @param[in]  len: data length.
 * @return     crc result.
 */
unsigned short crc16 (unsigned char *pD, int len);


#endif /* OTA_H_ */
